Ext.ns("Ext.ux.alisoft.Portal");
Ext.ux.alisoft.Portal = function(config){
	config = config || {};
	Ext.applyIf(config, {
            margins:'5 5 5 0',
            columnCount:3
	});
	this.columnCount=config.columnCount;
	this.columnWidths=[];
	if(!config.columnWeigh||config.columnWeigh.length!=this.columnCount){
		for(var i=0;i<this.columnCount;i++){
			this.columnWidths.push(1/this.columnCount);
		}
	}else{
		var sum=0;
		for(var i=0;i<config.columnWeigh.length;i++){
			sum+=config.columnWeigh[i];
		}
		for(var i=0;i<this.columnCount;i++){
			this.columnWidths.push(config.columnWeigh[i]/sum);
		}
	}
	Ext.ux.alisoft.Portal.superclass.constructor.call(this, config);
	this.insertColumn(this.columnCount-1);
}
Ext.extend(Ext.ux.alisoft.Portal,Ext.Panel, {
    layout: 'column',
    id:'portal',
    autoScroll:true,
    cls:'x-portal',
    region:'center',
    defaultType: 'portalcolumn',

    initComponent : function(){
        Ext.ux.alisoft.Portal.superclass.initComponent.call(this);
    	if(!this.items){
            this.initItems();
        }
        this.addEvents({
            validatedrop:true,
            beforedragover:true,
            dragover:true,
            beforedrop:true,
            drop:true
        });
    },

    initEvents : function(){
        Ext.ux.alisoft.Portal.superclass.initEvents.call(this);
        this.dd = new Ext.ux.alisoft.Portal.DropZone(this, this.dropConfig);
    },
    
    addPortlet : function(portlet){
    	var min=0,minCol=0,i=0;
    	if(this.items.itemAt(0)){
    		min=this.items.itemAt(0).items.getCount();
    	}
    	for(;i<this.columnCount;i++){
    		if(!this.items.itemAt(i)){
				this.insertColumn(i).add(portlet);
    			return;
    		}
    		if(this.items.itemAt(i).items.getCount()<min){
    			min=this.items.itemAt(i).items.getCount();
    			minCol=i;
    		}
    	}    	
    	this.items.itemAt(minCol).add(portlet);
    },
    
    insertPortlet : function(portlet,col,row){ 
    	if(col==undefined){
    		this.addPortlet(portlet);
    		return;
    	}
    	if(col>=this.columnCount){
    		col=this.columnCount-1;
    	}
    	if(col<0){
    		col=0;
    	}
    	if (!this.items.itemAt(col)) {
			this.insertColumn(col).add(portlet);
			return;
		}
    	if(row==undefined||row>this.items.itemAt(col).items.getCount()){
    		row=this.items.itemAt(col).items.getCount();
    	}
    	if(row<0){
    		row=0;
    	}
    	this.items.itemAt(col).insert( row, portlet) ;
    },
    
    insertColumn : function(col) {
    	for(var i=0;i<=col;i++){
    		if(!this.items.itemAt(i)){
				var column = new Ext.ux.alisoft.PortalColumn({
					columnWidth : this.columnWidths[i],
					style : 'padding:5px 5px 5px 5px'
				});
				this.items.add(column);
	    		if(i==col){
					return column;
	    		}
    		}
    	}
	},
    
    removePortlet : function(portlet,autoDestroy){
    	var pos = this.getPortletIndex(portlet);
    	if(pos){
    		this.removePortletAt(pos.col,pos.row,autoDestroy);
    	}
    },
    
    removePortletAt : function(col,row,autoDestroy){
    	if(this.items.itemAt(col)&&this.items.itemAt(col).getComponent(row)){
    		//this.items.itemAt(col).getComponent(row).el.dom.parentNode.removeChild(this.items.itemAt(col).getComponent(row).el.dom);
    		this.items.itemAt(col).remove(this.items.itemAt(col).getComponent(row),autoDestroy);
    	}
    },
    
    removeAll : function(autoDestroy){
    	for(var i=0;i<this.items.getCount();i++){
    		if(this.getComponent(i)){
    			this.remove(this.getComponent(i),autoDestroy);
    			i--;
    		}
    	}
    },
    
    getPortletIndex : function(portlet){
    	if(!portlet||!portlet.getId){
    		return;
    	}
    	for(var i=0;i<this.items.getCount();i++){
    		for(var j=0;j<this.items.itemAt(i).items.getCount();j++){
    			if(this.items.itemAt(i).getComponent(j).getId()==portlet.getId()){
    				return {col:i,row:j};
    			}
    		}
    	}
    	return;
    },
    
    resetColumn : function(columnCount){
    	this.columnCount=columnCount;
    	var portlets = [];
    	for(var j=0;j<this.getMaxRowCounts();j++){
	    	for(var i=0;i<this.items.getCount();i++){
	    		if(this.items.itemAt(i)&&this.items.itemAt(i).getComponent(j)){
	    			portlets.push(this.items.itemAt(i).getComponent(j));
	    		}
	    	}
    	}
    	for(var i=0;i<this.items.getCount();i++){
    		this.remove(this.getComponent(i));
    		i--;
    	}    	
    	for(var i=0;i<portlets.length;i++){    		
    		this.addPortlet(portlets[i]);
    	}
    },
    
    initPortlets : function(portlets){
    	if(portlets&&portlets.length){
    		this.removeAll();
    		for(var i=0;i<portlets.length;i++){
    			this.addPortlet(portlets[i]);
    		}
    	}
    },
        
    getMaxRowCounts : function(){
    	var max=0,i=0;
    	for(;i<this.items.getCount();i++){
    		if(this.items.itemAt(i)&&this.items.itemAt(i).items&&this.items.itemAt(i).items.getCount()>max){
    			max=this.items.itemAt(i).items.getCount();
    		}
    	}    
    	return max;
    }
});
Ext.reg('portal', Ext.ux.alisoft.Portal);


Ext.ux.alisoft.Portal.DropZone = function(portal, cfg){
    this.portal = portal;
    Ext.dd.ScrollManager.register(portal.body);
    Ext.ux.alisoft.Portal.DropZone.superclass.constructor.call(this, portal.bwrap.dom, cfg);
    portal.body.ddScrollConfig = this.ddScrollConfig;
};

Ext.extend(Ext.ux.alisoft.Portal.DropZone, Ext.dd.DropTarget, {
    ddScrollConfig : {
        vthresh: 50,
        hthresh: -1,
        animate: true,
        increment: 200
    },

    createEvent : function(dd, e, data, col, c, pos){
        return {
            portal: this.portal,
            panel: data.panel,
            columnIndex: col,
            column: c,
            position: pos,
            data: data,
            source: dd,
            rawEvent: e,
            status: this.dropAllowed
        };
    },

    notifyOver : function(dd, e, data){
        var xy = e.getXY(), portal = this.portal, px = dd.proxy;

        // case column widths
        if(!this.grid){
            this.grid = this.getGrid();
        }

        // handle case scroll where scrollbars appear during drag
        var cw = portal.body.dom.clientWidth;
        if(!this.lastCW){
            this.lastCW = cw;
        }else if(this.lastCW != cw){
            this.lastCW = cw;
            portal.doLayout();
            this.grid = this.getGrid();
        }

        // determine column
        var col = 0, xs = this.grid.columnX, cmatch = false;
        for(var len = xs.length; col < len; col++){
            if(xy[0] < (xs[col].x + xs[col].w)){
                cmatch = true;
                break;
            }
        }
        // no match, fix last index
        if(!cmatch){
            col--;
        }

        // find insert position
        var p, match = false, pos = 0,
            c = portal.items.itemAt(col),
            items = c.items.items;

        for(var len = items.length; pos < len; pos++){
            p = items[pos];
            var h = p.el.getHeight();
            if(h !== 0 && (p.el.getY()+(h/2)) > xy[1]){
                match = true;
                break;
            }
        }

        var overEvent = this.createEvent(dd, e, data, col, c,
                match && p ? pos : c.items.getCount());

        if(portal.fireEvent('validatedrop', overEvent) !== false &&
           portal.fireEvent('beforedragover', overEvent) !== false){

            // make sure proxy width is fluid
            px.getProxy().setWidth('auto');

            if(p){
                px.moveProxy(p.el.dom.parentNode, match ? p.el.dom : null);
            }else{
                px.moveProxy(c.el.dom, null);
            }

            this.lastPos = {c: c, col: col, p: match && p ? pos : false};
            this.scrollPos = portal.body.getScroll();

            portal.fireEvent('dragover', overEvent);

            return overEvent.status;;
        }else{
            return overEvent.status;
        }

    },

    notifyOut : function(){
        delete this.grid;
    },

    notifyDrop : function(dd, e, data){
        delete this.grid;
        if(!this.lastPos){
            return;
        }
        var c = this.lastPos.c, col = this.lastPos.col, pos = this.lastPos.p;

        var dropEvent = this.createEvent(dd, e, data, col, c,
                pos !== false ? pos : c.items.getCount());

        if(this.portal.fireEvent('validatedrop', dropEvent) !== false &&
           this.portal.fireEvent('beforedrop', dropEvent) !== false){

            dd.proxy.getProxy().remove();
            dd.panel.el.dom.parentNode.removeChild(dd.panel.el.dom);
            if(pos !== false){
                c.insert(pos, dd.panel);
            }else{
                c.add(dd.panel);
            }
            
            c.doLayout();

            this.portal.fireEvent('drop', dropEvent);

            // scroll position is lost on drop, fix it
            var st = this.scrollPos.top;
            if(st){
                var d = this.portal.body.dom;
                setTimeout(function(){
                    d.scrollTop = st;
                }, 10);
            }

        }
        delete this.lastPos;
        //this.portal.doLayout();
    },

    // internal cache of body and column coords
    getGrid : function(){
        var box = this.portal.bwrap.getBox();
        box.columnX = [];
        this.portal.items.each(function(c){
             box.columnX.push({x: c.el.getX(), w: c.el.getWidth()});
        });
        return box;
    }
});
